package com.jeasonzhao.commons.basic;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public final class IntegerPairHelper
{
    private static final String KEY_ID = "#16719c38-3431-4f0d-836b-a7c0c90c361c#";
    private static final String KEY_FIELD_NAME = "#4bbd8c0b-7af3-489c-b410-2af32ec8c38e#";
    private static final String KEY_NAME = "#df0807d5-0a9f-4aee-9bf5-eec308ac5e86#";
    private static final String NULL_CLASS = "#85b7cf76-70e5-4109-97d8-92d1c3cd6c96#";
    private static final String KEY_CLASS = "#ea8c2d00-23c5-48c0-a690-732c23774ac1";
    private static java.util.Hashtable<Object,Object> m_hashTable2Cache = null;
    private IntegerPairHelper()
    {
    }
    static
    {
        m_hashTable2Cache = new java.util.Hashtable<Object,Object>();
    }
    private static void buildInternalHashtable(Class<?> cls)
    {
        if(null == cls)
        {
            return;
        }
        String strClassHashKey = generateClassKey(cls);
        if(m_hashTable2Cache.containsKey(strClassHashKey) == false)
        {
            synchronized(m_hashTable2Cache)
            {
                if(m_hashTable2Cache.containsKey(strClassHashKey) == false)
                {
//                    System.out.println(IntegerPairHelper.class.getName()+" init :"+cls.getName());
                    if(false == IntegerPair.class.isAssignableFrom(cls)) //we do not handle this.
                    {
                        m_hashTable2Cache.put(strClassHashKey,strClassHashKey);
                        return;
                    }
                    Field[] allF = cls.getFields();
                    IntegerPairCollection constantFields = new IntegerPairCollection();
                    for(int nField = 0;nField < allF.length;nField++)
                    {
                        Field f = allF[nField];
                        int nModifier = f.getModifiers();
                        if(Modifier.isStatic(nModifier)
                           && Modifier.isPublic(nModifier)
                           && IntegerPair.class.isAssignableFrom(f.getType()))
                        {
                            f.setAccessible(true);
                            IntegerPair obj = null;
                            try
                            {
                                obj = (IntegerPair) f.get(null); //we do not need a instance to get field value.
                            }
                            catch(IllegalAccessException ex)
                            {
                                //Ignore the exception and then continue
                                continue;
                            }
                            catch(IllegalArgumentException ex)
                            {
                                //Ignore the exception and then continue
                                continue;
                            }
                            constantFields.add(obj);
                            m_hashTable2Cache.put(generateFieldNameKey(cls,obj),f.getName());
                            m_hashTable2Cache.put(generateFindByIdKey(cls,obj.getId()),obj);
                            m_hashTable2Cache.put(generateFindByNameKey(cls,f.getName()),obj);
                            StringCollection alias = StringCollection.splitString(obj.getAliasNames(),",");
                            for(int na = 0;alias != null && na < alias.size();na++)
                            {
                                if(null != alias.get(na) && alias.get(na).trim().length() > 0)
                                {
                                    String fk = generateFindByNameKey(cls,alias.get(na));
                                    if(m_hashTable2Cache.containsKey(fk) == false)
                                    {
                                        m_hashTable2Cache.put(fk,obj);
                                    }
                                }
                            }
                        }
                    }
                    m_hashTable2Cache.put(generateConstantFiledsListKey(cls)
                                          ,constantFields.size() < 1 ? new IntegerPairCollection() : constantFields);
                    m_hashTable2Cache.put(strClassHashKey,strClassHashKey);
                } //end of if hashed(inner)
            } //end synchronized
        } //end of if hashed(outer)
    }

    private final static String generateFieldNameKey(Class<?> cls,IntegerPair p)
    {
        return generateClassKey(cls) + KEY_FIELD_NAME + p.getId();
    }

    private final static String generateFindByIdKey(Class<?> cls,int n)
    {
        return generateClassKey(cls) + KEY_ID + n;
    }

    private final static String generateFindByNameKey(Class<?> cls,String strKey)
    {
        return generateClassKey(cls) + KEY_NAME + strKey.toLowerCase();
    }

    private final static String generateClassKey(Class<?> cls)
    {
        return null == cls ? NULL_CLASS : cls.getName();
    }

    private final static String generateConstantFiledsListKey(Class<?> cls)
    {
        return generateClassKey(cls) + KEY_CLASS;
    }

    public static IntegerPairCollection constantFields(Class<?> cls)
    {
        if(null == cls)
        {
            return null;
        }
        buildInternalHashtable(cls);
        return(IntegerPairCollection) m_hashTable2Cache.get(generateConstantFiledsListKey(cls));
    }

    public static String getConstantFieldName(IntegerPair p)
    {
        if(null == p)
        {
            return null;
        }
        buildInternalHashtable(p.getClass());
        return(String) m_hashTable2Cache.get(generateFieldNameKey(p.getClass(),p));
    }

    public static IntegerPair find(Class<?> cls,int nCheck)
    {
        if(null == cls)
        {
            return null;
        }
        buildInternalHashtable(cls);
        return (IntegerPair) m_hashTable2Cache.get(generateFindByIdKey(cls,nCheck));
    }

    protected static IntegerPair find(Class<?> cls,String str)
    {
        return find(cls,str,null);
    }

    protected static IntegerPair find(Class<?> cls,String strName,IntegerPair defaultV)
    {
        if(null == cls || strName == null || strName.trim().length() < 1)
        {
            return defaultV;
        }
        buildInternalHashtable(cls);
        IntegerPair ret = (IntegerPair) m_hashTable2Cache.get(generateFindByNameKey(cls,strName));
        return null == ret ? defaultV : ret;
    }
}
